package com.scpii.api.service.user.impl;

import java.text.MessageFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;

import com.scpii.api.common.Constants;
import com.scpii.api.common.aop.ActionTypeAspect;
import com.scpii.api.common.aop.ActionTypeAspect.PointConfig;
import com.scpii.api.common.base.ResponseThreadlocal;
import com.scpii.api.common.job.ApnsJob;
import com.scpii.api.domain.user.UserActionState;
import com.scpii.api.domain.user.UserActions;
import com.scpii.api.domain.user.UserActions.ActionType;
import com.scpii.api.domain.user.UserPointHistory;
import com.scpii.api.domain.user.UserShare;
import com.scpii.api.domain.user.Users;
import com.scpii.api.persistence.user.UserActionStateMapper;
import com.scpii.api.persistence.user.UserActionsMapper;
import com.scpii.api.persistence.user.UserPointHistoryMapper;
import com.scpii.api.persistence.user.UserShareMapper;
import com.scpii.api.persistence.user.UsersMapper;
import com.scpii.api.service.user.UserActionsService;
import com.scpii.api.util.PrincipalUtil;

@Service
public class UserActionsServiceImpl implements UserActionsService {

	private Log logger = LogFactory.getLog(ApnsJob.class);

	@Resource
	private UserActionsMapper userActionsMapper;

	@Resource
	private UsersMapper usersMapper;

	@Resource
	private UserPointHistoryMapper userPointHistoryMapper;

	@Resource
	private UserActionStateMapper userActionStateMapper;

	@Resource
	private UserShareMapper userShareMapper;

	@Override
	public List<UserActions> selectBySelective(UserActions userActions) {
		return userActionsMapper.selectBySelective(userActions);
	}

	@Override
	public List<UserActions> selectByTargetAndActionTypes(Long targetId,
			String[] actionTypes) {
		return userActionsMapper.selectByTargetAndActionTypes(targetId,
				actionTypes);
	}

	@Override
	public List<UserActions> selectBySelectiveWithSingle(UserActions userActions) {
		return userActionsMapper.selectBySelectiveWithSingle(userActions);
	}

	@Override
	public void insertSelective(UserActions record) {
		userActionsMapper.insertSelective(record);
	}

	@Override
	public void deleteByPrimaryKey(Long id) {
		userActionsMapper.deleteByPrimaryKey(id);
	}

	@Override
	public List<UserActions> selectUserStatusByTargetAndActionTypes(
			Long userId, Long targetId, String[] types) {
		return userActionsMapper.selectUserStatusByTargetAndActionTypes(userId,
				targetId, types);
	}

	@Override
	public void deleteByWithInTypes(UserActions record, String[] actionTypes) {
		userActionsMapper.deleteByWithInTypes(record, actionTypes);
	}

	@Override
	public void updateTableCountByColoumAndId(String table, Long id,
			String column, Integer count) {
		userActionsMapper.updateTableCountByColoumAndId(table, id, column,
				null, count);
	}

	@Override
	public void insertSelective(UserActions record, PointConfig config) {
		userActionsMapper.insertSelective(record);
		if (config == null) {
			return;
		}
		if (logger.isInfoEnabled()) {
			logger.info("the config is: " + config.toString());
		}
		if (config.isMathMaxIn()) {
			if (!isMaxIn(config)) {
				if (logger.isInfoEnabled()) {
					logger.info("is maxIn true");
				}
				return;
			}
		}
		Users users = usersMapper.selectByPrimaryKey(PrincipalUtil
				.getPrincipal().getId());
		if (users == null) {
			return;
		}
		usersMapper.updateRankPointById(PrincipalUtil.getPrincipal().getId(),
				config.getAddPoints());

		UserPointHistory history = new UserPointHistory();
		history.setUserActionId(record.getId());
		history.setPointConfigId(config.getId());
		history.setAddPoints(config.getAddPoints());
		history.setCreateBy(PrincipalUtil.getPrincipal().getId());
		history.setCreateDt(new Date());
		history.setUserId(PrincipalUtil.getPrincipal().getId());
		history.setPoints(users.getRankPoint() == null ? 0 : users
				.getRankPoint() + config.getAddPoints());
		history.setLastPoint(users.getRankPoint() == null ? 0 : users
				.getRankPoint());
		userPointHistoryMapper.insertSelective(history);
		String tips = MessageFormat.format(Constants.INTEGRAL_TIPS_TEMPLATE,
				config.getAddPoints());
		ResponseThreadlocal.getResponse().setTips(tips);
	}

	@Override
	public void updateCountByUserAction(UserActions record, int count) {
		UserActionState recordState = new UserActionState();
		recordState.setActionType(record.getActionType());
		recordState.setUserId(record.getUserId());
		UserActionState persisState = userActionStateMapper
				.selectBySelective(recordState);
		if (persisState != null) {
			persisState.setCount(persisState.getCount() + count);
			persisState.setUpdateBy(record.getUserId());
			persisState.setUpdateDt(new Date());
			userActionStateMapper.updateByPrimaryKeySelective(persisState);
		} else {
			Integer actionTypeCount = userActionsMapper
					.selectCountByUserIdAndType(record.getUserId(),
							record.getActionType());
			recordState.setCount(actionTypeCount);
			recordState.setCreateBy(record.getUserId());
			recordState.setCreateDt(new Date());
			userActionStateMapper.insertSelective(recordState);
		}

		Map<String, Object> tableField = ActionTypeAspect.USER_ACTIONT_TYPE_TABLE_FIELD
				.get(record.getActionType());
		if (tableField == null) {
			return;
		}
		Object tables = tableField.get("TABLES");
		Object fields = tableField.get("FIELDS");
		Object ids = tableField.get("IDS");
		Map<String, String> tableConfig = getTableConfig(record.getTargetId(),
				tables, fields, ids);
		if (tableConfig != null) {
			userActionsMapper.updateTableCountByColoumAndId(
					tableConfig.get("TABLE"),
					Long.valueOf(tableConfig.get("TARGET_ID")),
					tableConfig.get("FIELD"), tableConfig.get("ID"), count);
		}
	}

	private Map<String, String> getTableConfig(Long id, Object containsTables,
			Object containsFields, Object containsIds) {
		Map<String, String> result = null;
		if (containsTables instanceof String[]) {
			String[] tables = (String[]) containsTables;
			for (int i = 0; i < tables.length; i++) {
				Long startPos = Constants.TABLE_PRIKARY_KEY_START_POSITION
						.get(tables[i]);
				if (StringUtils.startsWith(String.valueOf(id),
						String.valueOf(startPos))) {
					result = new HashMap<String, String>();
					if (StringUtils.startsWith(tables[i], "UNIVERSAL_")) {
						result.put("TABLE", StringUtils.replace(tables[i],
								"UNIVERSAL_", Constants.UNIVERSAL_SCHEMA + "."));
						Long targetId = (id - (Long.valueOf(startPos
								+ Constants.TABLE_PRIMARYKEY_MIDDLE)));
						result.put("TARGET_ID", String.valueOf(targetId));
					} else {
						result.put("TABLE", tables[i]);
						result.put("TARGET_ID", String.valueOf(id));
					}
					if (containsFields instanceof String[]) {
						result.put("FIELD", ((String[]) containsFields)[i]);
					} else {
						result.put("FIELD", (String) containsFields);
					}
					if (containsIds instanceof String[]) {
						result.put("ID", ((String[]) containsIds)[i]);
					} else {
						result.put("ID", (String) containsIds);
					}
					return result;
				}
			}
		} else if (containsTables instanceof String) {
			result = new HashMap<String, String>();
			result.put("TABLE", (String) containsTables);
			result.put("FIELD", (String) containsFields);
			result.put("ID", (String) containsIds);
			result.put("TARGET_ID", String.valueOf(id));
			return result;
		}
		return null;
	}

	private boolean isMaxIn(PointConfig pointConfig) {
		Date now = new Date();
		if (logger.isInfoEnabled()) {
			logger.info("config is " + pointConfig.toString() + " userid is "
					+ PrincipalUtil.getPrincipal().getId() + "now date is "
					+ now);
		}
		Integer count = userPointHistoryMapper
				.selectCountByPointConfigIdTimeIn(pointConfig.getId(),
						PrincipalUtil.getPrincipal().getId(),
						pointConfig.getTimeAfter(), now);

		if (logger.isInfoEnabled()) {

			logger.info("the history count is " + count);
		}
		return pointConfig.getMax() > count;
	}

	@Override
	public void insertSelective(UserActions record, PointConfig pointConfig,
			UserShare userShare) {
		if (ActionType.ACTIVITIES_SHARE.getValue().equals(
				record.getActionType())
				&& userShare != null) {
			userShare.setCreateDt(new Date());
			userShare.setUserId(PrincipalUtil.getPrincipal().getId());
			userShareMapper.insertSelective(userShare);
		}
		record.setObjectId(userShare.getId());
		insertSelective(record, pointConfig);
	}

	@Override
	public List<UserActions> selectByUserIdAndActionType(Long userId,
			String[] actionTypes) {
		return userActionsMapper.selectByUserIdAndActionType(userId,
				actionTypes);
	}
}
